#include "sensorcollection.h"

SensorCollection::SensorCollection()
{
	std::string path = "./config/save.nano";
	std::string json_path = "./config/config.json";
    std::string timeout_path = "./config/timeout.nano";

	load.parse_save_file(path);
	load.parse_port_file(json_path);
    load.parse_timeout_file(timeout_path);

	serial_infos = load.serials;
	save_path = load.save_file;
    timeout_path = load.timeout_file;

    // 保留：从配置读超时阈值
    if (load.timeout_seconds > 0) {
        timeout_threshold = std::chrono::seconds(load.timeout_seconds);
    }
}

SensorCollection::~SensorCollection()
{
    // 新增：先停止超时线程（如果还在运行）
    std::lock_guard<std::mutex> lock(timeout_thread_mutex);
    if (is_timeout_thread_running && timeout_check_thread.joinable())
    {
        stop_check_thread = true;
        timeout_check_thread.join();
    }


    std::this_thread::sleep_for(std::chrono::seconds(1)); // 休眠1秒，释放CPU
}

void SensorCollection::connect()
{
    std::string success_message;
    int success_count = 0;

    for (const auto& pair : serial_infos) {
        auto [key, value] = pair;

        if (!value.enable) {
            std::println("传感器 {} 已禁用，跳过连接", key);
            continue;
        }

        try {
            {
                std::lock_guard<std::mutex> lock(enable_sensor_mutex); // 加锁保护
                enable_sensor.push_back(key);
            }
            // 构造 SerialPort 对象（内部已通过 init_port 安全初始化）
            auto port = std::make_unique<SerialPort>(
                value.portName, value.baudRate, value.parity, value.dataBits, value.stopBits
            );

            auto [filename, header] = mkfile(key);

            auto exporter = std::make_unique<CSVExporter>(filename, header);


            // 检查串口是否真的打开（双重保险）
            if (port->IsOpen()) {
                success_message += std::format("{{{}}}: (端口: {}, 波特率: {})\n",
                    key, value.portName, value.baudRate);
                config_parameters(port.get(), key);
                success_count++;
                serialports[key] = std::move(port);
                exporters[key] = std::move(exporter);

                {
                    std::lock_guard<std::mutex> lock(urls_mutex); // 加锁保护
                    urls[key] = value.url;
                }

            }
            else {
                std::println("传感器 {} 串口已创建但未打开，跳过", key);
            }
        }
        catch (const std::exception& e) {
            // 捕获 SerialPort 构造函数中可能向上传播的异常（如内存分配失败）
            std::println("传感器 {} 创建串口失败: {}", key, e.what());
        }
        catch (...) {
            std::println("传感器 {} 创建串口发生未知错误", key);
        }
    }

    // 打印连接结果
    std::println("\n串口连接完成：成功 {} 个，失败 {} 个",
        success_count, serial_infos.size() - success_count);
    if (!success_message.empty()) {
        std::println("成功连接列表:\n{}", success_message);
    }
}

void SensorCollection::config_parameters(SerialPort* port, const std::string& name)
{
    if (name == COMPASS) {

        port->write_to_serial("0x68 0x05 0x00 0x0C 0x02 0x13", true);
    }
    else if (name == HUMITURE) {
        port->write_to_serial("0xFA 0x03 0x00 0x64 0x00 0x01 0xD0 0x5E", true);
        port->write_to_serial("0x01 0x03 0x00 0x00 0x00 0x02 0xC4 0x0B", true);
    }
}

void SensorCollection::start_mm_timer(int intervalMs)
{
    stop_mm_timer();  // 确保先停止已有定时器

    // 设置定时器：精度intervalMs毫秒，回调函数TimerProc，传递当前对象指针作为用户数据
    m_timer_id = timeSetEvent(
        intervalMs,               // 定时间隔（毫秒）
        1,                        // 精度（毫秒，0为最高精度）
        timer_proc,                // 回调函数
        (DWORD_PTR)this,          // 传递当前对象指针到回调
        TIME_PERIODIC | TIME_CALLBACK_FUNCTION  // 周期性触发 + 函数回调模式
    );

    if (m_timer_id == 0)
    {
        std::print("创建多媒体定时器失败，错误码: {}", GetLastError());
        return;
    }

    // 提升定时器线程优先级（确保实时性）
    HANDLE hTimerThread = OpenThread(THREAD_SET_INFORMATION, FALSE, GetCurrentThreadId());
    if (hTimerThread)
    {
        SetThreadPriority(hTimerThread, THREAD_PRIORITY_TIME_CRITICAL);
        CloseHandle(hTimerThread);
    }

    // 2. 新增：启动超时检查线程（确保只启动一次）
    std::lock_guard<std::mutex> lock(timeout_thread_mutex);
    if (!is_timeout_thread_running)
    {
        stop_check_thread = false;  // 重置停止标志
        timeout_check_thread = std::thread(&SensorCollection::check_all_sensor_timeout, this);
        is_timeout_thread_running = true;
        std::println("✅ 超时检查线程已启动（与多媒体定时器同步）");
    }
}


void SensorCollection::stop_mm_timer()
{
    // 1. 停止多媒体定时器（原有逻辑保留）
    if (m_timer_id != 0)
    {
        timeKillEvent(m_timer_id);
        m_timer_id = 0;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    // 2. 新增：停止超时检查线程（确保安全停止）
    std::lock_guard<std::mutex> lock(timeout_thread_mutex);
    if (is_timeout_thread_running && timeout_check_thread.joinable())
    {
        stop_check_thread = true;  // 通知线程停止
        timeout_check_thread.join();  // 等待线程退出
        is_timeout_thread_running = false;
        std::println("✅ 超时检查线程已停止（与多媒体定时器同步）");
    }
}
void SensorCollection::timer_proc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
    SensorCollection* sc = reinterpret_cast<SensorCollection*>(dwUser);

    std::vector<std::string> enables;
    std::unordered_map<std::string, std::string> urls_copy;
    
    //std::println("定时器启动成功");

    // 加锁读取 enable_sensor
    {
        std::lock_guard<std::mutex> lock(sc->enable_sensor_mutex);
        enables = sc->enable_sensor;
    }

    // 加锁读取 urls 并拷贝（避免后续访问时锁竞争）
    {
        std::lock_guard<std::mutex> lock(sc->urls_mutex);
        urls_copy = sc->urls;
    }

    bool transfer = false;
    if (sc->count == 9) {
        sc->count = 0;
        transfer = true;
    }
    auto now = std::chrono::system_clock::now();

    for (const std::string& name : sc->enable_sensor) {
        sc->read_sensor(name, now);
        sc->transfer(name);

        send_remote_x010_data();

        //std::println("传感器的名字 {}", name);

        if (transfer) {
            post_sensor_data(name, urls_copy[name]);
        }
    }
    sc->count++;
}

void SensorCollection::read_sensor(const std::string& name, const std::chrono::system_clock::time_point& now) {
    auto port_it = serialports.find(name);
    if (port_it == serialports.end()) {
        std::println("传感器 {} 未连接，无法读取数据", name);
        return;
    }

    auto port = port_it->second.get();
    port->ReadOnceAsync(
        // 成功读取回调（有数据）
        [this, name, now](const std::string& data) {
            if (!data.empty()) {
                std::lock_guard<std::mutex> lock(records_mutex);
                // 确保记录存在（try_emplace 避免直接访问不存在的 key）
                auto [it, is_new] = sensor_records.try_emplace(name);
                it->second.latest_data = data;
                it->second.last_updated = now;  // 有新数据就更新时间
            }
            else {
                std::println("为什么会读到零呢？很奇怪");
            }
        },
        // 错误回调（明确断连场景）
        [this, name](const std::string& err) {
            std::println("❌ 传感器 {} 读取错误: {}", name, err);
        }
    );
}

void SensorCollection::transfer(const std::string& name)
{
    std::lock_guard<std::mutex> lock(records_mutex);  // 线程安全保护
    auto it = sensor_records.find(name);

    if (it == sensor_records.end()) {
        std::println("传感器 {} 暂无记录数据", name);
        return;
    }

    // 获取记录中的时间和数据
    const auto& record = it->second;
    //std::println("传输传感器 {} 的数据 - 时间: {}, 内容: {}",
    //    name,
    //    std::chrono::duration_cast<std::chrono::seconds>(
    //        record.last_updated.time_since_epoch()
    //    ).count(),  // 转换为秒级时间戳便于显示
    //    record.latest_data
    //);

    std::string message = record.latest_data;

    std::string data = get_last_message(name, message);
    std::vector<double> values = parse_sensor_data(name, data);

    if (name == SEATRAC) {
        std::vector<double> x010 = receive_remote_x010_data(data);
        for (double v : x010) {
            values.push_back(v);
        }
    }

    // 检查该传感器的 CSV 导出器是否存在
    auto exporter_it = exporters.find(name);
    if (exporter_it == exporters.end() || !exporter_it->second) {
        std::println("传感器 {} 未初始化 CSV 导出器", name);
        return;
    }

    // 传入记录中的时间戳（last_updated）和数值列表，调用 AddRecord
    exporter_it->second->AddRecord(record.last_updated, values);

}

std::pair<std::string, std::string> SensorCollection::mkfile(const std::string& name) {
    // 1. 修剪 save_path 的前后空白
    std::string sp = trim_ws(save_path);
    //std::print("mkfile - 修剪后 save_path: [{}]\n", sp);
    if (sp.empty()) {
        std::print("警告：save_path 为空，路径生成可能失败！\n");
        return { "", "" };
    }

    // 2. 生成时间戳（推荐用 seconds 或 ms（不带小数点））
    std::string timestamp = get_chrono_timestamp();
    timestamp = sanitize_for_filename(timestamp);
    //std::print("mkfile - 时间戳目录名: [{}]\n", timestamp);

    // 3. 构造 path（使用 std::filesystem::path，自动处理分隔符）
    std::filesystem::path base_dir = std::filesystem::path(sp).lexically_normal();
    std::filesystem::path timestamp_dir = base_dir / timestamp;
    std::filesystem::path file_path = timestamp_dir / sanitize_for_filename(name + ".csv");

    std::string file_path_str = file_path.string();
    //std::print("mkfile - 完整路径: [{}]\n", file_path_str);

    // 4. 创建目录
    try {
        std::filesystem::create_directories(timestamp_dir);
        std::print("mkfile - 成功创建时间戳目录: [{}]\n", timestamp_dir.string());
    }
    catch (const std::filesystem::filesystem_error& e) {
        std::print("mkfile - 创建时间戳目录失败: [{}]，原因: {}\n",
            timestamp_dir.string(), e.what());
        return { "", "" };
    }

    // 5. 获取表头
    std::string header = get_header(name);
    //std::print("mkfile - 传感器[{}]的表头: [{}]\n", name, header);

    return { file_path_str, header };
}

std::string SensorCollection::get_chrono_timestamp()
{
    using namespace std::chrono;
    auto now = system_clock::now();
    auto now_s = time_point_cast<seconds>(now);
    std::time_t t = system_clock::to_time_t(now_s);
    std::tm tm;
#ifdef _WIN32
    localtime_s(&tm, &t);
#else
    localtime_r(&t, &tm);
#endif
    char buf[32];
    if (std::strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", &tm) == 0) {
        return "unknown_time";
    }
    return std::string(buf);
}

std::string SensorCollection::trim_ws(const std::string& s)
{
    auto first = s.find_first_not_of(" \t\r\n");
    if (first == std::string::npos) return {};
    auto last = s.find_last_not_of(" \t\r\n");
    return s.substr(first, last - first + 1);
}

std::string SensorCollection::sanitize_for_filename(std::string s)
{
    const std::string forbidden = R"(<>:"\/|?*)";
    for (char& c : s) {
        if (std::isspace((unsigned char)c)) c = '_'; // 空白改为下划线
        else if (forbidden.find(c) != std::string::npos) c = '_';
    }
    return s;
}

void SensorCollection::check_all_sensor_timeout()
{
    while (!stop_check_thread) {
        std::this_thread::sleep_for(check_interval);
        auto now = std::chrono::system_clock::now();

        std::lock_guard<std::mutex> lock(records_mutex);
        for (auto& [sensor_name, record] : sensor_records) {
            // 跳过从未有过数据的传感器
            if (record.last_updated == std::chrono::system_clock::time_point{}) {
                continue;
            }

            // 计算超时时间
            auto duration = std::chrono::duration_cast<std::chrono::seconds>(
                now - record.last_updated
            );

            // 确保告警标记存在（默认未打印）
            auto [alert_it, alert_new] = sensor_alerted.try_emplace(sensor_name, false);

            // 超时且未打印：打印信息并标记
            if (duration >= timeout_threshold && !alert_it->second) {
                std::println("⚠️  传感器 {} 超时：已超过 {} 秒无新数据",
                    sensor_name, timeout_threshold.count());
                post_timeout_data(sensor_name, urls[sensor_name]);
                alert_it->second = true;
            }
            // 恢复有数据：重置标记（下次超时可重新打印）
            else if (duration < timeout_threshold && alert_it->second) {
                alert_it->second = false;
            }
        }
    }
}